package jsu.blogger.websocket;

import com.alibaba.fastjson2.JSONObject;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import jsu.blogger.handler.WebSocketHandler;
import jsu.blogger.pojo.Message;
import jsu.blogger.pojo.WebSocketMessage;
import jsu.blogger.service.inter.MessageService;
import jsu.blogger.util.MessageUtil;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Controller
@ServerEndpoint(value = "/websocket/{uid}/{token}")
public class WebSocketServer {
    private static MessageService messageService;
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    private static Map<String, Session> onlineUserList = new ConcurrentHashMap<>();
    private static Map<String, ArrayList<String>> tempMessageList = new ConcurrentHashMap<>();
    @Autowired
    public void setMessageService(MessageService messageService) {
        WebSocketServer.messageService = messageService;
    }
    public static Map<String, Session>  getOnlineUserList(){
        return onlineUserList;
    }
    public static Map<String,ArrayList<String>>  getTempMessageList(){
        return tempMessageList;
    }
    @OnOpen
    public void onOpen(Session session) {
        String userId = session.getPathParameters().get("uid");
        try {
            if (!WebSocketHandler.isTokenValid(session)) {
                session.getBasicRemote().sendText("Token不合法！");
                session.close();
                return;
            }
            // 将用户会话添加到在线用户列表
            if(onlineUserList.containsKey(userId)){
                Session oldSession =onlineUserList.remove(userId);
                //该用户账号已经登录，将原来的账户退出登录。
                log.info(userId+"重复登录账户!");
                oldSession.getBasicRemote().sendText(MessageUtil.toJsonWebSocketMessage(2,"您的账号在别处被登录",null));
                oldSession.close();
            }
            onlineUserList.put(userId, session);
            log.info("用户uid：" + userId + " 已经成功连接服务器");

            // 检查是否有需要推送的消息
            List<String> tempMessages = tempMessageList.remove(userId);
            if (tempMessages != null && !tempMessages.isEmpty()) {
                //推送消息
                for (String tempMessage : tempMessages) {
                    WebSocketMessage webSocketMessage= MessageUtil.parseJsonToWebSocketMessage(tempMessage);
                    Message message=MessageUtil.parseJsonToMessage((JSONObject) webSocketMessage.getData());
                    session.getBasicRemote().sendText(tempMessage);
                    // System.out.println("推送消息给用户uid：" + userId + " : " + message);
                }
            }
        } catch (IOException e) {
            log.error("Error during opening WebSocket connection for userId: {}", userId, e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @OnMessage
    public void onMessage(String msg, @NotNull Session session) {
        try {
            WebSocketMessage webSocketMessage= MessageUtil.parseJsonToWebSocketMessage(msg);
            if(webSocketMessage.getCode()==0)return;//心跳消息，用于保持连接状态
                Message message=MessageUtil.parseJsonToMessage((JSONObject) webSocketMessage.getData());
                log.info("收到消息 " + webSocketMessage);
                // 检查接收者是否在线
                if (onlineUserList.containsKey(String.valueOf(message.getReceiverId()))) {
                    // 在线用户，直接发送消息
                    Session targetSession = onlineUserList.get(String.valueOf(message.getReceiverId()));
                    targetSession.getBasicRemote().sendText(msg);
                    log.info("用户" + message.getReceiverId() + " 在线，消息直接发送");
                    message.setIsAccepted(true);
                    messageService.keepMessage(message);
                } else {
                    // 不在线用户，暂存消息
                    ArrayList<String> tempMessages = tempMessageList.computeIfAbsent(String.valueOf(message.getReceiverId()), k -> new ArrayList<>());
                    tempMessages.add(msg);
                    log.info("发给用户" + message.getReceiverId() + "不在线，消息已暂存: " + message);
                    messageService.keepMessage(message);
                }
        } catch (Exception e) {
            log.error("Error processing message: {}", msg, e);
        }
    }

    @OnClose
    public void onClose(Session session) {
        String userId = session.getPathParameters().get("uid");
        onlineUserList.remove(userId);
        log.info("用户uid：" + userId + " websocket已关闭");
        try {
            session.close();
        } catch (IOException e) {
            log.error("Error closing session for userId: {}", userId, e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        String userId = session.getPathParameters().get("uid");
        try {
            log.error("WebSocket error for userId: {}, sessionId: {}", userId, session.getId(), error);
            if(!session.isOpen())
            session.close();
        } catch (Exception e) {
            log.error("Error closing session on error for userId: {}", userId, e);
        }
    }

}
